/*
 * Copyright 2014 JootMir Project
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 * Support: http://www.jootmir.org
 */
package org.jootmir.client.core;

import static org.lwjgl.opengl.GL11.*;

import org.jootmir.client.core.texture.Texture;

/**
 * OpenGL绑定类
 * <br>
 * 包含显卡纹理绘制
 * <br>
 * 显卡功能参数
 * <br>
 * 显卡功能支持项等信息
 * <br>
 * 如果使用本类来绘制纹理，大多数方法会将颜色置为白色
 * <br>
 * <b>除非使用以"AllowColor"结尾的方法，此种方法会保留颜色(即您可以在调用方法前先绑定颜色)</b>
 */
public final class OpenGL {

	/* 单例 */
	private static OpenGL single = new OpenGL();
	private OpenGL() { }
	
	/** 获取进程唯一实例 */
	public static OpenGL get() {
		return single;
	}
	
	/**
	 * 绘制2D纹理图
	 * 
	 * @param tex
	 * 		要绘制的纹理
	 * @param x
	 * 		绘制左上角
	 * @param y
	 * 		绘制右下角
	 */
	public void drawTexture2DNormal(Texture tex, int x, int y) {
		if(tex == null) return;
		drawTex2D(tex.getTextureID(), x, y, tex.getWidth(), tex.getHeight());
	}
	
	/**
	 * 绘制2D纹理图
	 * <br>
	 * 允许保留绘制前设置的颜色进行蒙板(混合)
	 * 
	 * @param tex
	 * 		纹理
	 * @param x
	 * 		绘制左上角
	 * @param y
	 * 		绘制右下角
	 */
	public void drawTexture2DNormalAllowColor(Texture tex, int x, int y) {
		drawTexture2DNormalAllowColor(tex, 0, 0, tex.getWidth(), tex.getHeight(), 0, 0, tex.getWidth(), tex.getHeight());
	}
	
	/**
	 * 绘制2D纹理图
	 * <br>
	 * 只绘制其部分
	 * <br>
	 * 允许保留绘制前设置的颜色进行蒙板(混合)
	 * 
	 * @param tex
	 * 		纹理
	 * @param desLTx
	 * 		绘制目的地左上角x坐标
	 * @param desLTy
	 * 		绘制目的地左上角y坐标
	 * @param desWidth
	 * 		绘制区域宽度
	 * @param desHeight
	 * 		绘制区域高度
	 * @param srcLTx
	 * 		绘制纹理区域左上角x坐标
	 * @param srcLTy
	 * 		绘制纹理区域左上角y坐标
	 * @param srcWidth
	 * 		绘制纹理区域宽度
	 * @param srcHeight
	 * 		绘制纹理区域高度
	 */
	public void drawTexture2DNormalAllowColor(Texture tex, int desLTx, int desLTy, int desWidth, int desHeight, int srcLTx, int srcLTy, int srcWidth, int srcHeight) {
		if(tex == null) return;
		fixBlendAdd();
		drawTex2DAllowColor(tex.getTextureID(), desLTx, desLTy, desWidth, desHeight, srcLTx / 1f / tex.getWidth(), srcLTy / 1f / tex.getHeight(), srcWidth / 1f / tex.getWidth(), srcHeight / 1f / tex.getHeight());
		fixBlendNormal();
	}
	
	/**
	 * 绘制纹理，允许颜色
	 * 
	 * @param textureId
	 * 		纹理Id
	 * @param desLTx
	 * 		要绘制的目的地左上角x坐标
	 * @param desLTy
	 * 		要绘制的目的地左上角y坐标
	 * @param desWith
	 * 		要绘制的宽度
	 * @param desHeight
	 * 		要绘制的高度
	 * @param srcLTx
	 * 		绘制的纹理区域左上角x坐标；0.0是纹理的左侧，0.5是纹理的中点，1.0是纹理的右侧
	 * @param srcLTy
	 * 		绘制的纹理区域左上角y坐标；0.0是纹理的顶部，0.5是纹理的中点，1.0是纹理的底部
	 * @param srcWidth
	 * 		绘制的纹理区域宽度(同样是比例，相对于整个纹理的宽度)
	 * @param srcHeight
	 * 		绘制的纹理区域高度(同样是比例，相对于真个纹理的高度)
	 */
	private void drawTex2DAllowColor(int textureId, int desLTx, int desLTy, int desWith, int desHeight, float srcLTx, float srcLTy, float srcWidth, float srcHeight) {
		glTranslatef(desLTx, desLTy, 0);
		glBindTexture(GL_TEXTURE_2D, textureId);
		glBegin(GL_QUADS);
			glTexCoord2f(srcLTx, srcLTy);
			glVertex2f(0, 0);
			glTexCoord2f(srcLTx + srcWidth, srcLTy);
			glVertex2f(desWith, 0);
			glTexCoord2f(srcLTx + srcWidth, srcLTy + srcHeight);
			glVertex2f(desWith, desHeight);
			glTexCoord2f(srcLTx, srcLTy + srcHeight);
			glVertex2f(0, desHeight);
		glEnd();
		glBindTexture(GL_TEXTURE_2D, 0);
		glLoadIdentity();
	}
	
	/**
	 * 绘制2D纹理图
	 * <br>
	 * 启用混合
	 * 
	 * @param tex
	 * 		要绘制的纹理<br>纹理会与已绘制的纹理进行颜色混合
	 * @param x
	 * 		绘制区域左上角
	 * @param y
	 * 		绘制区域右下角
	 */
	public void drawTexture2DAdd(Texture tex, int x, int y) {
		if(tex == null) return;
		fixBlendAdd();
		drawTex2D(tex.getTextureID(), x, y, tex.getWidth(), tex.getHeight());
		fixBlendNormal();
	}
	
	/** 在制定区域绘制纹理图片，绘制区域以(x,y)为左上角。以width为宽度，以height为高度 */
	private void drawTex2D(int textureId, int x, int y, int width, int height) {
		glTranslatef(x, y, 0);
		glColor4f(1.0f, 1.0f, 1.0f, 1.0f); // 清除颜色
		glBindTexture(GL_TEXTURE_2D, textureId);
		glBegin(GL_QUADS);
			glTexCoord2f(0, 0);
			glVertex2f(0, 0);
			glTexCoord2f(1, 0);
			glVertex2f(width, 0);
			glTexCoord2f(1, 1);
			glVertex2f(width, height);
			glTexCoord2f(0, 1);
			glVertex2f(0, height);
		glEnd();
		glBindTexture(GL_TEXTURE_2D, 0);
		glLoadIdentity();
	}

	/** 将纹理色彩混合模式恢复为普通<br>即只处理透明色 */
	private void fixBlendNormal() {
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	}
	/** 将纹理色彩混合模式设置为叠加当前色彩，保留目标色彩所有颜色 */
	private void fixBlendAdd() {
		glBlendFunc(GL_SRC_COLOR, GL_ONE);
	}
}